package com.siam.package_order.controller.member;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.siam.package_common.service.AliyunSms;
import com.siam.package_common.util.CommonUtils;
import com.siam.package_order.service.OrderRefundProcessService;
import com.siam.package_order.service.OrderRefundService;
import com.siam.package_order.service.OrderService;
import com.siam.package_weixin_basic.service.WxPublicPlatformNotifyService;
import com.siam.package_weixin_pay.config.WxPayConfig;
import com.siam.package_weixin_pay.entity.TransferToUserRequest;
import com.siam.package_weixin_pay.entity.TransferToUserResponse;
import com.siam.package_weixin_pay.util.WXPayUtility;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;

@Data
@Slf4j
@Service
public class WxPayV3Service {

    @Value("${spring.profiles.active}")
    private String profilesActive;

    @Autowired
    private WxPayConfig wxPayConfig;

    @Resource(name = "orderServiceImpl")
    private OrderService orderService;

    @Autowired
    private OrderRefundService orderRefundService;

    @Autowired
    private OrderRefundProcessService orderRefundProcessService;

    @Autowired
    private AliyunSms aliyunSms;

    @Autowired
    private WxPublicPlatformNotifyService wxPublicPlatformNotifyService;

    private int socketTimeout = 10000;// 连接超时时间，默认10秒

    private int connectTimeout = 30000;// 传输超时时间，默认30秒

    private static RequestConfig requestConfig;// 请求器的配置

    private static CloseableHttpClient httpClient;// HTTP请求器

    private PrivateKey privateKey;

    private PublicKey wechatPayPublicKey;

    private static String METHOD = "POST";
    private static String PATH = "/v3/fund-app/mch-transfer/transfer-bills";

    @PostConstruct
    public void initKey() {
//        privateKey = WXPayUtility.loadPrivateKeyFromPath(wxPayConfig.getPrivateKeyFilePath());
//        wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wxPayConfig.getWechatPayPublicKeyFilePath());

        ClassPathResource classPathResourceByPrivateKey = new ClassPathResource(wxPayConfig.getPrivateKeyFilePath());
        InputStream inputStreamByPrivateKey = null;
        ClassPathResource classPathResourceBPublicKey = new ClassPathResource(wxPayConfig.getWechatPayPublicKeyFilePath());
        InputStream inputStreamByPublicKey = null;
        try {
            inputStreamByPrivateKey = classPathResourceByPrivateKey.getInputStream();
            privateKey = WXPayUtility.loadPrivateKeyFromStream(inputStreamByPrivateKey);

            inputStreamByPublicKey = classPathResourceBPublicKey.getInputStream();
            wechatPayPublicKey = WXPayUtility.loadPublicKeyFromStream(inputStreamByPublicKey);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String encrypt(String plainText) {
        return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText);
    }

    /**
     * 商家转账到零钱(企业付款到零钱替代方案)
     */
    public JSONObject payToBalance(TransferToUserRequest request){
        //只有正式环境才能执行
//        if(!this.getProfilesActive().equals("prod")){
//            return null;
//        }
        try {
            request.appid = wxPayConfig.getAppId();
            request.notifyUrl = wxPayConfig.getPayToBalanceV3NotifyUrl();
            request.userName = encrypt(request.getUserName());
            log.info("[商家转账到零钱],request=" + JSON.toJSONString(request));

            TransferToUserResponse response = run(request);
            log.info("[商家转账到零钱],response=" + response);

            // 记录前端跳转确认收款页面需要的信息
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("mchId", wxPayConfig.getMchId());
            jsonObject.put("appId", wxPayConfig.getAppId());
            jsonObject.put("package", response.getPackageInfo());

            return jsonObject;
        } catch (WXPayUtility.ApiException e) {
            // 请求失败，根据状态码执行不同的逻辑
            e.printStackTrace();

            String errorMsg = "";
            String err_code = (String) e.getErrorCode();
            String err_code_des = (String) e.getErrorMessage();
            errorMsg = request.getOutBillNo() + "订单企业付款到零钱失败，err_code : " + err_code + "，err_code_des : " + err_code_des;
            log.error(errorMsg);

            //微信公众号消息通知管理员
            wxPublicPlatformNotifyService.sendFatalErrorMessage(WxPublicPlatformNotifyService.jpOpenId, errorMsg, CommonUtils.getFunctionLocation(), "无", new Date(), "请管理员及时处理");

            return null;
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.toString(), e);

            String errorMsg = request.getOutBillNo()+"订单企业付款到零钱失败，catch Exception : " + e.toString();
            //微信公众号消息通知管理员
            wxPublicPlatformNotifyService.sendFatalErrorMessage(WxPublicPlatformNotifyService.jpOpenId, errorMsg, CommonUtils.getFunctionLocation(), "无", new Date(), "请管理员及时处理");

            return null;
        }
    }

    public TransferToUserResponse run(TransferToUserRequest request) {
        String reqBody = WXPayUtility.toJson(request);

        Request.Builder reqBuilder = new Request.Builder().url(wxPayConfig.getPayToBalanceV3Url());
        reqBuilder.addHeader("Accept", "application/json");
        reqBuilder.addHeader("Wechatpay-Serial", wxPayConfig.getWechatPayPublicKeyId());
        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(wxPayConfig.getMchId(), wxPayConfig.getCertificateSerialNo(), privateKey, METHOD, PATH, reqBody));
        reqBuilder.addHeader("Content-Type", "application/json");
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
        reqBuilder.method(METHOD, requestBody);
        Request httpRequest = reqBuilder.build();

        // 发送HTTP请求
        OkHttpClient client = new OkHttpClient.Builder().build();
        try (Response httpResponse = client.newCall(httpRequest).execute()) {
            String respBody = WXPayUtility.extractBody(httpResponse);
            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
                // 2XX 成功，验证应答签名
                WXPayUtility.validateResponse(this.wxPayConfig.getWechatPayPublicKeyId(), this.wechatPayPublicKey,
                        httpResponse.headers(), respBody);

                // 从HTTP应答报文构建返回数据
                return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
            } else {
                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Sending request to " + wxPayConfig.getPayToBalanceV3Url() + " failed.", e);
        }
    }
}